package com.sgzn.sgpay.service.impl;

import com.sgzn.sgpay.enums.SgsResponseCode;
import com.sgzn.sgpay.exception.SgpayException;
import com.sgzn.sgpay.model.request.*;
import com.sgzn.sgpay.model.request.bank.SgsBankFourElementsRequest;
import com.sgzn.sgpay.model.response.LoginRespDto;
import com.sgzn.sgpay.model.response.SgsResultResponse;
import com.sgzn.sgpay.persistence.dao.TMerchantAccountMapper;
import com.sgzn.sgpay.persistence.dao.TMerchantMapper;
import com.sgzn.sgpay.persistence.dao.TShowIncomeRecordMapper;
import com.sgzn.sgpay.persistence.domain.*;
import com.sgzn.sgpay.service.SgsMchPrivManageService;
import com.sgzn.sgpay.service.SgsMerchantDiscountRuleService;
import com.sgzn.sgpay.service.SgsMerchantManageService;
import com.sgzn.sgpay.service.SgsMobileMsgVerifyService;
import com.sgzn.sgpay.service.bank.SgsBankCardQueryService;
import com.sgzn.sgpay.service.bank.SgsBankVerifyService;
import com.sgzn.sgpay.service.config.MerchantAppConfig;
import com.sgzn.sgpay.service.converter.AssembleSgsCommonHandle;
import com.sgzn.sgpay.service.converter.MerchantReqConverter;
import com.sgzn.sgpay.service.support.HttpRequestHandler;
import com.sgzn.sgpay.service.support.SgsResponseUtil;
import com.sgzn.sgpay.service.support.SubMchManager;
import com.sgzn.sgpay.util.ArgsUtils;
import com.sgzn.sgpay.util.TranslateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;

/**
 * 商户管理服务
 * @author zhongzhongyong
 * @version Id: SgsMerchantManageServiceImpl.java, v 0.1 2018/4/17 22:19 zhongzhongyong Exp $$
 */
@Service
@Slf4j
public class SgsMerchantManageServiceImpl implements SgsMerchantManageService {

    @Autowired
    private TMerchantMapper tMerchantMapper;

    @Autowired
    private TMerchantAccountMapper tMerchantAccountMapper;

    @Resource
    private SgsMobileMsgVerifyService sgsMobileMsgVerifyService;

    @Resource
    private SgsMchPrivManageService sgsMchPrivManageService;

    @Autowired
    private HttpRequestHandler httpRequestHandler;

    @Autowired
    private MerchantAppConfig merchantAppConfig;

    @Autowired
    private SubMchManager subMchManager;

    @Autowired
    private SgsBankCardQueryService sgsBankCardQueryService;

    @Autowired
    private SgsMerchantDiscountRuleService sgsMerchantDiscountRuleService;

    @Autowired
    private AssembleSgsCommonHandle assembleSgsCommonHandle;

    @Autowired
    private SgsBankVerifyService sgsBankVerifyService;

    @Autowired
    private TShowIncomeRecordMapper tShowIncomeRecordMapper;


    /**
     * 新增主商户
     * @param request
     * @return
     */
    @Override
    @Transactional(readOnly = false, isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public SgsResultResponse<String> add(SgsMerchantAddRequest request) {
        try{
            //校验两个密码是否相同
            String pwd1 = request.getPassword().trim();
            String pwd2 = request.getConfirmPwd().trim();
            ArgsUtils.check(pwd1.equals(pwd2), SgsResponseCode.C_MCH_LOGIN_PWD_NOT_EQL.getResponseCode(), SgsResponseCode.C_MCH_LOGIN_PWD_NOT_EQL.getResponseDesc());

            //检测商户联系方式是否已经注册
            TMerchantExample exp = new TMerchantExample();
            TMerchantExample.Criteria cra = exp.createCriteria();
            cra.andContactEqualTo(request.getContact());
            int count = tMerchantMapper.countByExample(exp);
            ArgsUtils.notPositive(count, SgsResponseCode.C_REPEAT_MCH_CONTACT.getResponseCode(), SgsResponseCode.C_REPEAT_MCH_CONTACT.getResponseDesc());

            //校验验证码是否有效
            checkCode(request.getInitiationID(),request.getContact(),request.getCode(),request.getLoginChannel(),request.getReqTime());

            //获取OpenId
            log.info("根据小程序发送的TempCode请求微信获取OpenId");
            String initId = request.getInitiationID();
            LoginReqDto dto = assmbleReqDto(request);
            LoginRespDto loginRespDto = httpRequestHandler.invokeJscode2session(dto,initId);
            log.info("请求微信获取OpenId{}",loginRespDto);

            //新增商户基础信息
            TMerchant tMerchant = MerchantReqConverter.addReqConvert(request);
            //商户号
            request.setMerchantId(tMerchant.getMerchantId());
            //openId
            tMerchant.setOpenId(loginRespDto.getOpenId());
            //UnionId
            tMerchant.setUnionid(loginRespDto.getUnionId());


            int result = tMerchantMapper.insertSelective(tMerchant);
            if(result == 0){
                throw new Exception("tMerchantMapper add  Exception");
            }

            //新增商户账户信息
            TMerchantAccount tMerchantAccount = MerchantReqConverter.addReqConvert(request,tMerchant.getMerchantId());
            int accountResult = tMerchantAccountMapper.insertSelective(tMerchantAccount);
            if(accountResult == 0){
                throw new Exception("tMerchantAccountMapper add  Exception");
            }

            //赋予权限
            SgsMchPrivBatchAddRequest batchAddRequest = MerchantReqConverter.getPrivBatchAddRequest(request,tMerchant.getMerchantId());
            sgsMchPrivManageService.batchInsertByMchId(batchAddRequest);

            //初始化商户消费优惠规则
            sgsMerchantDiscountRuleService.addMerchantDiscountRule(getSgsMerchantDiscountRuleAddRequest(request));

            //初始化商户今日收益和累计收益信息
            initShowIncomeRecord(request.getMerchantId());

            //返回商户id
            return SgsResponseUtil.INSTANCE.success(tMerchant.getMerchantId());
        }catch (SgpayException e){
            log.error("业务异常.{}{}",e.getCode(),e.getDesc());
            return SgsResponseUtil.INSTANCE.fail(e.getCode(),e.getDesc());
        }catch (Exception e){
            log.error("[{}]. 插入响应流水日志异常.", request.getInitiationID(),e);
            return SgsResponseUtil.INSTANCE.fail(SgsResponseCode.C_DB_EXCEPTION.getResponseCode(),
                    SgsResponseCode.C_DB_EXCEPTION.getResponseDesc());
        }
    }

    /**
     * 初始化商户今日收益和累计收益信息
     * @param merchantId
     */
    private void initShowIncomeRecord(String merchantId) {
        TShowIncomeRecord tShowIncomeRecord = new TShowIncomeRecord();
        tShowIncomeRecord.setMerchantId(merchantId);
        tShowIncomeRecord.setCreatedBy(merchantId);
        tShowIncomeRecord.setCreatedAt(new Date());
        tShowIncomeRecord.setUpdatedBy(merchantId);
        tShowIncomeRecord.setUpdatedAt(new Date());
        tShowIncomeRecordMapper.insertSelective(tShowIncomeRecord);
    }

    /**
     * 重置密码
     * @param request
     * @return
     */
    @Override
    @Transactional(readOnly = false, isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public SgsResultResponse<String>  resetPwd(SgsMchResetPwdRequest request){
        try{
            //校验两个密码是否相同
            String pwd1 = request.getPassword().trim();
            String pwd2 = request.getConfirmPwd().trim();
            ArgsUtils.check(pwd1.equals(pwd2), SgsResponseCode.C_MCH_LOGIN_PWD_NOT_EQL.getResponseCode(), SgsResponseCode.C_MCH_LOGIN_PWD_NOT_EQL.getResponseDesc());

            //检测商户联系方式是否已经注册
            TMerchantExample exp = new TMerchantExample();
            TMerchantExample.Criteria cra = exp.createCriteria();
            cra.andContactEqualTo(request.getMobile());
            int count = tMerchantMapper.countByExample(exp);
            ArgsUtils.positive(count, SgsResponseCode.C_MCH_MOBILE_NOT_REGIS.getResponseCode(), SgsResponseCode.C_MCH_MOBILE_NOT_REGIS.getResponseDesc());

            //校验验证码是否有效
//            checkCode(request.getInitiationID(),request.getMobile(),request.getCode(),request.getLoginChannel(),request.getReqTime());
            //测试过程 使用 123456作为验证码
            ArgsUtils.check("123456".equals(request.getCode()), SgsResponseCode.C_CODE_OVERTIME.getResponseCode(), SgsResponseCode.C_CODE_OVERTIME.getResponseDesc());
            //更新商户密码
            TMerchant tMerchant = MerchantReqConverter.updateReqConvert(request);
            //条件对象
            TMerchantExample tMerchantExample = new TMerchantExample();
            TMerchantExample.Criteria criteria = tMerchantExample.createCriteria();
            criteria.andContactEqualTo(request.getMobile());
            int result = tMerchantMapper.updateByExampleSelective(tMerchant,tMerchantExample); //更新结果为0，并不能说明是Update错误
            if(result == 0){
                throw new Exception("tMerchantMapper update Exception");
            }
            //返回"1"
            return SgsResponseUtil.INSTANCE.success("1");
        }catch (SgpayException e){
            log.error("业务异常.{}{}",e.getCode(),e.getDesc());
            return SgsResponseUtil.INSTANCE.fail(e.getCode(),e.getDesc());
        }catch (Exception e){
            log.error("[{}]. 插入响应流水日志异常.", request.getInitiationID(),e);
            return SgsResponseUtil.INSTANCE.fail(SgsResponseCode.C_DB_EXCEPTION.getResponseCode(),
                    SgsResponseCode.C_DB_EXCEPTION.getResponseDesc());
        }
    }

    /**
     * 新增子商户
     * @param request
     * @return 商户ID
     */
    @Override
    public SgsResultResponse<String> addSubMch(SgsSubMchAddRequest request) {
        try{
            //校验两个密码是否相同
            String pwd1 = request.getPassword().trim();
            String pwd2 = request.getConfirmPwd().trim();
            ArgsUtils.check(pwd1.equals(pwd2), SgsResponseCode.C_MCH_LOGIN_PWD_NOT_EQL.getResponseCode(), SgsResponseCode.C_MCH_LOGIN_PWD_NOT_EQL.getResponseDesc());

            //检测商户联系方式是否已经注册
            TMerchantExample exp = new TMerchantExample();
            TMerchantExample.Criteria cra = exp.createCriteria();
            cra.andContactEqualTo(request.getContact());
            int count = tMerchantMapper.countByExample(exp);
            ArgsUtils.notPositive(count, SgsResponseCode.C_REPEAT_MCH_CONTACT.getResponseCode(), SgsResponseCode.C_REPEAT_MCH_CONTACT.getResponseDesc());

            //新增商户基础信息
            TMerchant subMch = MerchantReqConverter.addSubMchReqConvert(request);
            tMerchantMapper.insertSelective(subMch);

            //赋予子商户菜单访问权限
            String[] privIds = request.getPrivIds().split(",");
            subMchManager.setSubMchPrivs(privIds,subMch.getMerchantId());

            //赋予子商户门店访问权限
            String[] shopIds = request.getShopIds().split(",");
            subMchManager.setSubMchRelatShop(shopIds,subMch.getMerchantId());

            //返回商户id
            return SgsResponseUtil.INSTANCE.success(subMch.getMerchantId());
        }catch (SgpayException e){
            log.error("业务异常.{}{}",e.getCode(),e.getDesc());
            return SgsResponseUtil.INSTANCE.fail(e.getCode(),e.getDesc());
        }catch (Exception e){
            log.error("[{}]. 插入响应流水日志异常.", request.getInitiationID(),e);
            return SgsResponseUtil.INSTANCE.fail(SgsResponseCode.C_DB_EXCEPTION.getResponseCode(),
                    SgsResponseCode.C_DB_EXCEPTION.getResponseDesc());
        }
    }

    /**
     * 修改子商户
     * @param request
     * @return
     */
    @Override
    public SgsResultResponse<String> updateSubMch(SgsSubMchUpdateRequest request) {
        try{
            String subMchId = request.getSubMchId();
            //校验子商户和主商户是否存在关联
            ArgsUtils.check(subMchManager.checkMainSubMchRelat(request.getMchId(), subMchId), SgsResponseCode.C_MCH_NOT_FOUND.getResponseCode(), SgsResponseCode.C_MCH_NOT_FOUND.getResponseDesc());

            //删除子商户旧菜单访问权限
            subMchManager.deleteHisPriv(subMchId);

            //赋予子商户新菜单访问权限
            String[] privIds = request.getPrivIds().split(",");
            subMchManager.setSubMchPrivs(privIds,subMchId);

            //删除子商户旧门店访问权限
            subMchManager.deleteHisSubMchShop(subMchId);

            //赋予子商户新门店访问权限
            String[] shopIds = request.getShopIds().split(",");
            subMchManager.setSubMchRelatShop(shopIds,subMchId);

            //返回商户id
            return SgsResponseUtil.INSTANCE.success("success");
        }catch (SgpayException e){
            log.error("业务异常.{}{}",e.getCode(),e.getDesc());
            return SgsResponseUtil.INSTANCE.fail(e.getCode(),e.getDesc());
        }catch (Exception e){
            log.error("[{}]. 插入响应流水日志异常.", request.getInitiationID(),e);
            return SgsResponseUtil.INSTANCE.fail(SgsResponseCode.C_DB_EXCEPTION.getResponseCode(),
                    SgsResponseCode.C_DB_EXCEPTION.getResponseDesc());
        }
    }

    /**
     * 删除子商户
     * @param request
     * @return
     */
    @Override
    public SgsResultResponse<String> deleteSubMch(SgsSubMchDeleteRequest request) {
        try{
            String subMchId = request.getSubMchId();
            //校验子商户和主商户是否存在关联
            ArgsUtils.check(subMchManager.checkMainSubMchRelat(request.getMchId(),subMchId), SgsResponseCode.C_MCH_NOT_FOUND.getResponseCode(), SgsResponseCode.C_MCH_NOT_FOUND.getResponseDesc());

            //删除子商户旧菜单访问权限
            subMchManager.deleteHisPriv(subMchId);

            //删除子商户旧门店访问权限
            subMchManager.deleteHisSubMchShop(subMchId);

            //删除子商户基本信息和会话信息
            subMchManager.deleteSubMch(subMchId);

            //返回商户id
            return SgsResponseUtil.INSTANCE.success("success");
        }catch (SgpayException e){
            log.error("业务异常.{}{}",e.getCode(),e.getDesc());
            return SgsResponseUtil.INSTANCE.fail(e.getCode(),e.getDesc());
        }catch (Exception e){
            log.error("[{}]. 插入响应流水日志异常.", request.getInitiationID(),e);
            return SgsResponseUtil.INSTANCE.fail(SgsResponseCode.C_DB_EXCEPTION.getResponseCode(),
                    SgsResponseCode.C_DB_EXCEPTION.getResponseDesc());
        }
    }

    /**
     * 获取商户消费优惠规则服务新增请求类
     * @param request
     * @return
     */
    private SgsMerchantDiscountRuleAddRequest getSgsMerchantDiscountRuleAddRequest(SgsMerchantAddRequest request) {
        SgsMerchantDiscountRuleAddRequest sgsMerchantDiscountRuleAddRequest = new SgsMerchantDiscountRuleAddRequest();
        assembleSgsCommonHandle.assemble(request, sgsMerchantDiscountRuleAddRequest);
        sgsMerchantDiscountRuleAddRequest.setMchId(request.getMerchantId());
        return sgsMerchantDiscountRuleAddRequest;
    }

    /**
     * 验证码是否有效
     * @param initId
     * @param mobile
     * @param code
     * @param loginChannel
     * @param reqTime
     * @return
     */
    private boolean checkCode(String initId,String mobile,String code, String loginChannel, Date reqTime){
        SgsMobileMsgVerifyQueryRequest target = new SgsMobileMsgVerifyQueryRequest();
        target.setInitiationID(initId);
        target.setMobile(mobile);
        target.setVerifyCode(code);
        target.setLoginChannel(loginChannel);
        target.setReqTime(reqTime);
        SgsResultResponse<Boolean> resp = sgsMobileMsgVerifyService.isMobileMsgVerify(target);
        if(TranslateUtil.isSuccessAbs(resp.getErrorCode())){
            return true;
        }else{
            throw new SgpayException(resp.getErrorCode(),resp.getErrorMsg());
        }
    }


    /**
     * 更新商户基础信息（不包括账户信息）
     * @param request
     * @return
     */
    @Override
    public SgsResultResponse<String> updateBaseInfo(SgsMerchantBaseInfoUpdateRequest request) {
        try{
            //更新字段对象
            TMerchant tMerchant = MerchantReqConverter.updateReqConvert(request);
            //条件对象
            TMerchantExample tMerchantExample = new TMerchantExample();
            TMerchantExample.Criteria criteria = tMerchantExample.createCriteria();
            criteria.andMerchantIdEqualTo(request.getMchId());
            int result = tMerchantMapper.updateByExampleSelective(tMerchant,tMerchantExample);
            if(result == 0){
                throw new Exception("商户基础信息更新失败");
            }
            //返回商户id
            return SgsResponseUtil.INSTANCE.success(tMerchant.getMerchantId());
        }catch (Exception e){
            log.error("[{}]. 商户基础信息更新异常.", request.getInitiationID(),e);
            return SgsResponseUtil.INSTANCE.fail(SgsResponseCode.C_DB_EXCEPTION.getResponseCode(),
                    SgsResponseCode.C_DB_EXCEPTION.getResponseDesc());
        }
    }


    /**
     * 商户绑定银行卡/更新商户信息
     */
    @Override
    public SgsResultResponse<String> bindMerchantBankCardInfo(SgsMerchantBankCardUpdateRequest request) {
        try{
            //更新字段对象
            TMerchant tMerchantTarget = new TMerchant();
            //校验卡Bin
            SgsBankCardBinRequest sgsBankCardBinRequest = new SgsBankCardBinRequest();
            assembleSgsCommonHandle.assemble(request,sgsBankCardBinRequest);
            sgsBankCardBinRequest.setCardNo(request.getBankCardNo());
            SgsResultResponse<TBankCardBin> tBankCardBinSgsResultResponse = sgsBankCardQueryService.queryBankCardByCardNum(sgsBankCardBinRequest);
            if (tBankCardBinSgsResultResponse.getResult() == null){
                log.info("没找到卡Bin,不支持该银行卡");
                return SgsResponseUtil.INSTANCE.fail(SgsResponseCode.C_MCH_Bank_NOT_SUPPORT.getResponseCode(),
                        SgsResponseCode.C_MCH_Bank_NOT_SUPPORT.getResponseDesc());
            }

            //
            SgsBankFourElementsRequest sgsBankFourElementsRequest = new SgsBankFourElementsRequest();
            sgsBankFourElementsRequest.setCertNo( request.getCertCode());
            sgsBankFourElementsRequest.setBankcard( request.getBankCardNo());
            sgsBankFourElementsRequest.setMobile(request.getBankMobileNo());
            sgsBankFourElementsRequest.setRealName(request.getBankAccountName());
            assembleSgsCommonHandle.assemble(request,sgsBankFourElementsRequest);

            SgsResultResponse<String> bindSgsResultResponse =  sgsBankVerifyService.verify(sgsBankFourElementsRequest);

            if ( !bindSgsResultResponse.getErrorCode().equals("0") ){
                    log.info("银行卡信息有误，请核实{}",bindSgsResultResponse.getErrorMsg());
                return SgsResponseUtil.INSTANCE.fail(SgsResponseCode.C_MCH_Bank_NOT_CONSISTENT.getResponseCode(),
                        SgsResponseCode.C_MCH_Bank_NOT_CONSISTENT.getResponseDesc());
            }

            //更新商户信息
            tMerchantTarget.setBankAccountName(request.getBankAccountName());
            tMerchantTarget.setBankCardNo(request.getBankCardNo());
            tMerchantTarget.setBankMobileNo(request.getBankMobileNo());
            tMerchantTarget.setBankCardCode(request.getBankCardCode());
            tMerchantTarget.setCertCode(request.getCertCode());

            //条件对象
            TMerchantExample tMerchantExample = new TMerchantExample();
            TMerchantExample.Criteria criteria = tMerchantExample.createCriteria();
            criteria.andMerchantIdEqualTo(request.getMchId());
            int result = tMerchantMapper.updateByExampleSelective(tMerchantTarget,tMerchantExample);
            if(result == 0){
                throw new Exception("商户绑卡更新失败");
            }
            //返回商户id
            return SgsResponseUtil.INSTANCE.success(request.getMchId());
        }catch (Exception e){
            log.error("[{}]. 商户绑卡更新异常.", request.getInitiationID(),e);
            return SgsResponseUtil.INSTANCE.fail(SgsResponseCode.C_DB_EXCEPTION.getResponseCode(),
                    SgsResponseCode.C_DB_EXCEPTION.getResponseDesc());
        }
    }

    /**
     * 获取登录请求实体
     * @param request
     * @return
     */
    private LoginReqDto assmbleReqDto(SgsMerchantAddRequest request){
        LoginReqDto dto = new LoginReqDto();
        dto.setAppid(merchantAppConfig.getMerchantAppId());
        dto.setGrant_type(merchantAppConfig.getGrantType());
        dto.setSecret(merchantAppConfig.getMerchantSecret());
        dto.setJs_code(request.getTempCode()); //这个是验证码,需要的是小程序发过来的临时码?
        return dto;
    }

}
